package de.tum.wi.som.rcpsp.view;

import java.awt.Color;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYStepAreaRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.ApplicationFrame;

import de.tum.wi.som.rcpsp.entities.Activity;
import de.tum.wi.som.rcpsp.entities.ResourceAssignment;
import de.tum.wi.som.rcpsp.entities.Schedule;
import de.tum.wi.som.rcpsp.entities.TimePeriod;

public class RCPSPPieChart extends ApplicationFrame {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private Schedule schedule;

	public RCPSPPieChart(Schedule schedule) {
		super("RCPSP solution");
		this.schedule = schedule;
		XYDataset dataset = createDataset();
		JFreeChart chart = createChart(dataset);
		final ChartPanel chartPanel = new ChartPanel(chart);
		chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
		setContentPane(chartPanel);
	}

	public XYDataset createDataset() {
		List<TimePeriod> timePeriod = schedule.getTimePeriods();
		XYSeriesCollection dataset = new XYSeriesCollection();
		Map<String, XYSeries> activityXYSeriesMap = new HashMap<String, XYSeries>();
		Map<Integer, Integer> resourcesPerTimePeriod = new HashMap<Integer, Integer>();
		createXYSeries(activityXYSeriesMap, timePeriod, dataset);
		for (TimePeriod timeUnit : timePeriod) {
			List<ResourceAssignment> resourceAssignments = timeUnit
					.getResourceAssignments();
			int time = timeUnit.getTime();
			for (ResourceAssignment resAssignment : resourceAssignments) {
				XYSeries actualXYSeries = activityXYSeriesMap.get(getIdForActivity(resAssignment.getActivity()));
				Integer resourcesInTimePeriod = resourcesPerTimePeriod.get(time);
				int resourcesToAdd = resourcesInTimePeriod==null ? 0 : resourcesInTimePeriod;
				actualXYSeries.add(time, resourcesToAdd + resAssignment.getResourceUnits());
				resourcesPerTimePeriod.put(time, resourcesToAdd + resAssignment.getResourceUnits());
			}
		}

		
		return dataset;
	}

	private void createXYSeries(
			Map<String, XYSeries> activityIdentifier,
			List<TimePeriod> timePeriod, XYSeriesCollection dataset) {
		for (TimePeriod timePeriod2 : timePeriod) {
			List<ResourceAssignment> resourceAssignment = timePeriod2
					.getResourceAssignments();

			for (int i = 0; i < resourceAssignment.size(); i++) {
				Activity activity = resourceAssignment.get(i).getActivity();
				String id = getIdForActivity(activity);
				if (!activityIdentifier.containsKey(id)) {
					XYSeries xySeries = new XYSeries(id);
					dataset.addSeries(xySeries);
					activityIdentifier.put(id, xySeries);
				}
			}
		}

	}

	private String getIdForActivity(Activity activity) {
		return activity.getName() + " (" + activity.getUpperBound() + "/" + activity.getLowerBound() + ")";
	}

	/**
     * Creates a chart.
     * 
     * @param dataset  the dataset.
     * 
     * @return A chart.
     */
    private JFreeChart createChart(final XYDataset dataset) {
            
        final JFreeChart chart = ChartFactory.createXYStepAreaChart(
            "Limit: " + schedule.getWorkContentResource().getLimit() + ", MinBlockLength: " + schedule.getWorkContentResource().getMinBlockLength(),
            "Zeitperiode", "Resourcenbelastung",
            dataset,
            PlotOrientation.VERTICAL,
            true,  // legend
            true,  // tool tips
            false  // URLs
        );
        
        // color
        final XYPlot plot = chart.getXYPlot();
        plot.getRenderer().setSeriesPaint(0, Color.green);
        
        NumberAxis domainAxis = (NumberAxis)plot.getDomainAxis();
        domainAxis.setTickUnit(new NumberTickUnit(1.0));
        
        NumberAxis rangeAxis = (NumberAxis)plot.getRangeAxis();
        rangeAxis.setTickUnit(new NumberTickUnit(1.0));

        // fill shapes      
        final XYStepAreaRenderer rend = (XYStepAreaRenderer) plot.getRenderer();
        rend.setShapesFilled(true);

        return chart;        
    }
}
